﻿/*-------------------------------------------------------------------------
* 命名空间: WaferSelectV3.Extensions/CommonExtensions
* 类       名: CommonExtensions
* 功      能:  TD
* 时      间:  2024/5/5 16:14:45
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WaferSelectV3.Extensions
{
    public static class CommonExtensions
    {
        /// <summary>
        /// 获取异常信息的所有信息.
        /// StackTrace和Frames是.NET中异常处理和调试中非常重要的概念.
        /// StackTrace:是一个标识调用栈在某一个特定点的状态的对象.当程序运行的时候,每当 一个方法调用,
        /// 它就会被推送到调用栈上;当方法执行完毕返回时,它就被弹出调用堆栈.这个栈帮助程序跟踪到目前为止哪些方法已经被调用,
        /// 以及每个方法调用时的上下文.
        /// 当一个异常发生的时候,StackTrace捕获并记录了异常发生时的方法调用序列.
        /// StackTrace确实可以看作是一个在异常时刻捕获的函数调用序列集合，它记录了异常发生时的方法调用堆栈。而这个集合中的每一项，
        /// 也就是每个StackFrame，代表集合中的一个元素，包含了单个函数调用的相关信息。
        /// StackTrace：当异常被抛出时，.NET 运行时会自动创建StackTrace，这个StackTrace包含了从程序执行开始到异常发生点的方法调用序列。
        /// 这是一个方法调用历史的记录，显示了程序是如何“走到”抛出异常的点的。
        /// StackFrame：是StackTrace中的一个“快照”，包含了特定方法调用的信息，比如方法名、文件名和源代码行号（如果可用）。
        /// StackTrace由多个StackFrame组成，每个StackFrame对应于调用堆栈上的一个点。
        /// </summary>
        /// <param name="ex"></param>
        public static string GetFullException(this Exception ex)
        {
            var sb = new StringBuilder();
            string messageShow = ex.Message;
            var innerException = ex;
            while (innerException != null)
            {
                innerException = innerException.InnerException;
                messageShow = messageShow + " " + innerException?.Message;
            }
            sb.AppendLine($"异常消息: {messageShow}");
            sb.AppendLine($"所属程序集: {ex.Source}");
            sb.AppendLine($"异常发生函数: {ex.TargetSite}");



            // 获取堆栈跟踪信息
            // true参数表示尽可能捕获源信息(文件名,行号等)
            var st = new StackTrace(ex, true);
            var frames = st.GetFrames();
            if (frames != null)
            {
                foreach (var frame in frames)
                {
                    var filename = frame.GetFileName();
                    if (!string.IsNullOrWhiteSpace(filename))
                    {
                        sb.AppendLine($"异常发生的文件名: {filename}");
                        sb.AppendLine($"异常发生的行号: {frame.GetFileLineNumber()}");
                        sb.AppendLine($"异常发生的列号: {frame.GetFileColumnNumber()}");
                    }
                }
            }
            return sb.ToString();
        }
    }
}
